package com.lsh.ofc.core.handler;

import com.alibaba.dubbo.common.utils.NetUtils;
import com.alibaba.fastjson.JSON;
import com.lsh.ofc.core.constant.Constants;
import com.lsh.ofc.core.entity.OfcSupplier;
import com.lsh.ofc.core.mail.EmailHandler;
import com.lsh.ofc.core.redis.RedisTemplate;
import com.lsh.ofc.core.wumartbasic.IWumartBasicStrategy;
import com.lsh.ofc.proxy.context.WumartBasicContext;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.text.MessageFormat;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

/**
 * Project Name: lsh-ofc
 * @author panxudong
 * 北京链商电子商务有限公司
 * Desc: 类功能描述
 * Package Name: com.lsh.ofc.proxy.handler
 * Time: 2017-07-27 下午3:17
 */
@Service
public class WumartBasicHandler {

    private static final Logger logger = Logger.getLogger(WumartBasicHandler.class);
    private static String HOST = NetUtils.getLocalHost() + " " + System.getProperty("snowflake.node");
    @Autowired
    private List<IWumartBasicStrategy> strategies;
//    @Autowired
//    private OfcSupplierService ofcSupplierService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private EmailHandler emailHandler;

    @PostConstruct
    public void init() {
//        this.initConfig();

        new Timer().schedule(new WumartBasicHandler.CheckWumartBasicRedisInfoTask(), 300 * 1000, 300 * 1000);
    }

    public void updateConfig(OfcSupplier supplier) {
        String key = supplier.getId().toString();

        String redisLockKey = MessageFormat.format(Constants.OFC_SUPPLIER_CONFIG_UPDATE_LOCK, supplier.getId());
        if (!this.redisTemplate.lock(redisLockKey, 30)) {
            logger.warn("updating ofc supplier config... id:" + key);
            return;
        }

        logger.info("update ofc supplier config start. id:" + key);
        try {
            Integer regionCode = supplier.getRegionCode();
            Integer supplierOrg = supplier.getSupplierOrg();
            Integer supplierId = supplier.getSupplierId();

            String dc = supplier.getSupplierDc();
            String config = supplier.getConfig();

            String configRedisKey = this.getSupplyKey(String.valueOf(regionCode), String.valueOf(supplierOrg), String.valueOf(supplierId));
            if (!this.redisTemplate.hexists(configRedisKey, dc)) {
                this.redisTemplate.hset(configRedisKey, dc, config);
            } else {
                String targetConfig = this.redisTemplate.hget(configRedisKey, dc);
                this.setConfig(configRedisKey, dc, config, targetConfig);
            }
            logger.info("update ofc supplier config end. id:" + key);
        } catch (Throwable e) {
            logger.error("update ofc supplier config error. id:" + key);
            logger.error(e.getMessage(), e);
            this.handleException(e, "update", JSON.toJSONString(supplier));
        } finally {
            this.redisTemplate.unlock(redisLockKey);
        }
    }

    public String getConfigValue(WumartBasicContext context) {
        logger.info("redis customer context is " + JSON.toJSONString(context));
        IWumartBasicStrategy strategy = null;
        for (IWumartBasicStrategy iStrategy : strategies) {
            if (iStrategy.validate(context)) {
                strategy = iStrategy;
                break;
            }
        }

        if (strategy == null) {
            logger.info("getConfigValue strategy is null WumartBasicContext " + JSON.toJSONString(context));
            return null;
        }

        return strategy.getConfigValue(context);
    }

    private String getSupplyKey(String regionCode, String supplierOrg, String supplierId) {

        return MessageFormat.format(Constants.OFC_SUPPLIER_CONFIG, regionCode, supplierOrg, supplierId);
    }

//    private void initConfig() {
//        if (!this.redisTemplate.lock(Constants.OFC_SUPPLIER_CONFIG_LOCK, 120)) {
//            logger.warn("initializing ofc supplier config...");
//            return;
//        }
//
//        logger.info("initialize ofc supplier config start.");
//        try {
//            OfcSupplier params = new OfcSupplier();
//            List<OfcSupplier> list = this.ofcSupplierService.findList(params);
//
//            Map<String, Map<String, OfcSupplier>> supplierMap = new HashMap<>();
//            for (OfcSupplier supplier : list) {
//                Integer regionCode = supplier.getRegionCode();
//                Integer supplierOrg = supplier.getSupplierOrg();
//                Integer supplyId = supplier.getSupplierId();
//                String dc = supplier.getSupplierDc();
//
//                String regionCodeSupplyOrg = regionCode + ":" + supplierOrg + ":" + supplyId;
//
//                Map<String, OfcSupplier> suppliers = supplierMap.get(regionCodeSupplyOrg);
//                if (suppliers == null) {
//                    suppliers = new HashMap<>();
//                    supplierMap.put(regionCodeSupplyOrg, suppliers);
//                }
//
//                suppliers.put(supplier.getSupplierDc(), supplier);
//            }
//
//            for (Map.Entry<String, Map<String, OfcSupplier>> entry : supplierMap.entrySet()) {
//                String regionCodeSupplyOrg = entry.getKey();
//                String[] regionCodeSupplyOrgArray = regionCodeSupplyOrg.split(":");
//
//                String regionCode = regionCodeSupplyOrgArray[0];
//                String supplierOrg = regionCodeSupplyOrgArray[1];
//                String supplyId = regionCodeSupplyOrgArray[2];
//
//                Map<String, OfcSupplier> dcSupplierMap = entry.getValue();
//
//                String redisKey = this.getSupplyKey(regionCode, supplierOrg, supplyId);
//                Map<String, String> configs = this.redisTemplate.hgetAll(redisKey);
//
//                //修改redis里存在但是数据库修改的配置
//                if (configs != null && !configs.isEmpty()) {
//                    for (Map.Entry<String, String> config : configs.entrySet()) {
//                        String dc = config.getKey();
//                        //删除redis存在,数据库没有的配置
//                        if (!dcSupplierMap.containsKey(dc)) {
////                            this.redisTemplate.hdel(redisKey, dc);
//
//                        } else {//修改redis里存在但是数据库修改的配置
//                            OfcSupplier supplier = dcSupplierMap.get(dc);
//                            String sourceConfig = supplier.getConfig();
//                            String targetConfig = config.getValue();
//
//                            this.setConfig(redisKey, dc, sourceConfig, targetConfig);
//
//                            dcSupplierMap.remove(dc);
//                        }
//                    }
//                }
//
//                //添加数据库新怎的配置到redis
//                for (Map.Entry<String, OfcSupplier> supplierEntry : dcSupplierMap.entrySet()) {
//                    this.redisTemplate.hset(redisKey, supplierEntry.getKey(), supplierEntry.getValue().getConfig());
//                }
//            }
//
//            logger.info("initialize ofc supplier config end.");
//        } catch (Throwable e) {
//            logger.error("initialize ofc supplier config error.");
//            logger.error(e.getMessage(), e);
//            this.handleException(e, "initialize", "");
//        } finally {
//            this.redisTemplate.unlock(Constants.OFC_SUPPLIER_CONFIG_LOCK);
//        }
//    }

    private void setConfig(String redisKey, String dc, String sourceConfig, String targetConfig) {
        if (StringUtils.hasText(sourceConfig)) {
            if (!sourceConfig.equals(targetConfig)) {
                this.redisTemplate.hset(redisKey, dc, sourceConfig);
            }
        } else {
            if (StringUtils.hasText(targetConfig)) {
                this.redisTemplate.hdel(redisKey, dc);
            }
        }
    }

    private void handleException(Throwable throwable, String type, String params) {
        StringBuilder sb = new StringBuilder();
        sb.append("操作:").append(type).append("\nIP:").append(HOST).append("\n参数:").append(params).append("\n异常:")
                .append(ExceptionUtils.getStackTrace(throwable));
        this.emailHandler.buildEmail(EmailHandler.EmailTopic.SET_WUMART_CONFIG, sb.toString());
    }

    private class CheckWumartBasicRedisInfoTask extends TimerTask {

        @Override
        public void run() {
//            initConfig();
        }

    }

}
